home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / GLX / DBglxwidgetOpenGL / overlay.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  15.2 KB  |  647 lines

  1. /*
  2.  * overlay.c
  3.  *  Test routine for working with glxDraw widgets.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <errno.h>
  8.  
  9. #include <X11/Xlib.h>
  10. #include <X11/StringDefs.h>
  11. #include <X11/Intrinsic.h>
  12. #include <X11/keysym.h>
  13.  
  14. #include <Xm/Xm.h>
  15. #include <Xm/Frame.h>
  16.  
  17. #include "GlxMDraw.h"
  18. #ifndef USE_GL
  19. #include <GL/glu.h>
  20. #endif
  21.  
  22. #define USE_OVERLAY
  23.  
  24. int   oldx, oldy, curx, cury, dx, dy;
  25.  
  26. enum { SINGLE, DOUBLE } bufferMode;
  27. enum { MONO,   STEREO } stereoMode;
  28.  
  29. /* The GLX configuration parameter:
  30.  *     Double buffering
  31.  *    color index (default so unspecified)
  32.  *    overlay
  33.  *    nothing else special
  34.  */
  35.  
  36. #define OV_TYPE        2
  37.  
  38. #ifdef USE_GL
  39. static GLXconfig glxConfig [] = {
  40.     { GLX_NORMAL, GLX_DOUBLE, FALSE },
  41.     { GLX_NORMAL, GLX_BUFSIZE, GLX_NOCONFIG },
  42.     { GLX_OVERLAY, GLX_BUFSIZE, 2 },
  43.     { 0, 0, 0 }
  44. };
  45. #else
  46. static int glxConfig[] = {
  47. #ifdef USE_STEREO
  48.     GLX_DOUBLEBUFFER,
  49. #endif
  50.     GLX_RGBA,
  51.     GLX_RED_SIZE,3,
  52.     GLX_BLUE_SIZE,3,
  53.     GLX_GREEN_SIZE,3,
  54.     GLX_DEPTH_SIZE,12,
  55.     None,
  56. };
  57. static int glxConfigOverlay[] = {
  58.     GLX_LEVEL, 1,
  59.     GLX_BUFFER_SIZE, 4,
  60.     None
  61. };
  62. #endif
  63.  
  64. String fallback_resources[] = {
  65.     "*geometry: =750x600",
  66.     "*frame*shadowType: SHADOW_IN",
  67.     NULL
  68. };
  69.  
  70. struct 
  71. {
  72.     int width, height;
  73. }view;
  74.  
  75. Boolean use_pups=FALSE;    /* if TRUE, must use popup planes */
  76.  
  77. static XtAppContext app_context;
  78.  
  79. /* forward declarations of callbacks */
  80. static void exposeCB();
  81. static void overlayExposeCB();
  82. static void resizeCB();
  83. static void initCB();
  84. static void inputCB();
  85.  
  86. main (int argc, char *argv[])
  87. {
  88.     Arg            args[20];
  89.     int            n = 0;
  90.     Widget        toplevel, frame, glw;
  91.     Window        windows[3];
  92.  
  93.     /*----
  94.      * First, initialize the display.
  95.      *----*/
  96.  
  97.     toplevel = XtAppInitialize(&app_context, "4DgiftsGlx", 
  98.                    (XrmOptionDescList)NULL , 0,
  99. #if XtSpecificationRelease == 4
  100.                    (Cardinal*)&argc, 
  101. #else
  102.                    &argc, 
  103. #endif
  104.                    (String*)argv, 
  105.                    fallback_resources,
  106.                    (ArgList)NULL, 0);
  107.  
  108.     /*----
  109.      * Find out if we can use overlay planes (they exist),
  110.      * otherwise, use popup planes.  While we're at it,
  111.      * fix the glxConfig parameter to request popup planes
  112.      * instead of the default overlay planes (default because
  113.      * we defined it above).
  114.      *----*/
  115.  
  116. #ifdef USE_GL
  117.     if (getgdesc(GD_BITS_OVER_SNG_CMODE) < 2)
  118.     {
  119.     use_pups = TRUE;
  120.     glxConfig[OV_TYPE].buffer = GLX_POPUP;
  121.     }
  122. #endif
  123.  
  124.     /*----
  125.      * Create a frame widget to put the GLX widget into.
  126.      *----*/
  127.  
  128.     n = 0;
  129.     frame = XtCreateManagedWidget("frame",
  130.                   xmFrameWidgetClass,
  131.                   toplevel, args, n);
  132.  
  133.     /*----
  134.      * Set up the resources/arguments for the GLX widget and
  135.      * then create the widget.
  136.      *----*/
  137.  
  138.     n = 0;
  139.     XtSetArg(args[n], GlxNglxConfig, glxConfig); n++;
  140. #ifdef USE_OVERLAY
  141. #ifdef USE_GL
  142.     XtSetArg(args[n], use_pups?GlxNusePopup:GlxNuseOverlay, TRUE); n++;
  143. #else
  144.     XtSetArg(args[n], GlxNoverlayGlxConfig, glxConfigOverlay); n++;
  145. #endif
  146. #endif
  147. #ifdef USE_STEREO
  148.     XtSetArg(args[n], GlxNprovideStereoBuffer, TRUE); n++;
  149. #else
  150.     XtSetArg(args[n], GlxNprovideSingleBuffer, TRUE); n++;
  151. #endif
  152.     glw = XtCreateManagedWidget("glwidget",
  153.                   glxMDrawWidgetClass,
  154.                   frame, args, n);
  155.  
  156.     /*----
  157.      * This is just a flag to help me keep track of which window
  158.      * is up now.
  159.      *----*/
  160.  
  161.     bufferMode = SINGLE;
  162.     stereoMode = MONO;
  163.  
  164.     /*----
  165.      * Add required callbacks.
  166.      *----*/
  167.  
  168.     XtAddCallback(glw, GlxNexposeCallback, exposeCB, 0);
  169.     XtAddCallback(glw,
  170.           use_pups?GlxNpopupExposeCallback:GlxNoverlayExposeCallback,
  171.           overlayExposeCB, 0);
  172.     XtAddCallback(glw, GlxNresizeCallback, resizeCB, 0);
  173.     XtAddCallback(glw, GlxNginitCallback, initCB, 0);
  174.     XtAddCallback(glw, GlxNinputCallback, inputCB, 0);
  175.  
  176.     /*----
  177.      * Ok, now we can realize our widgets.
  178.      *----*/
  179.  
  180.     XtRealizeWidget(toplevel);
  181.  
  182.     /*----
  183.      * Notify the window manager of colormaps that we are using
  184.      * so it will switch them in for us automatically.
  185.      *----*/
  186.  
  187.     XtVaGetValues (glw,
  188.            use_pups ? GlxNpopupWindow : GlxNoverlayWindow,
  189.            &windows[0], NULL);
  190.     windows[1] = XtWindow (glw);
  191.     windows[2] = XtWindow (toplevel);
  192.     XSetWMColormapWindows (XtDisplay (toplevel), XtWindow (toplevel),
  193.                windows, 3);
  194.  
  195.     XtAppMainLoop(app_context);
  196.  
  197. }
  198.  
  199. /* Return the overlay window of the widget */
  200. Window overlayWindow(w)
  201. Widget w;
  202. {
  203.     Arg args[1];
  204.     Window overlayWindow;
  205.  
  206.     XtSetArg(args[0], use_pups?GlxNpopupWindow:GlxNoverlayWindow,
  207.          &overlayWindow);
  208.     XtGetValues(w, args, 1);
  209.     return (overlayWindow);
  210. }
  211. #ifndef USE_GL
  212. /* Return the overlay window of the widget */
  213. GLXContext overlayContext(w)
  214. Widget w;
  215. {
  216.     Arg args[1];
  217.     GLXContext overlayContext;
  218.  
  219.     XtSetArg(args[0], GlxNoverlayGlxContext, &overlayContext);
  220.     XtGetValues(w, args, 1);
  221.     return (overlayContext);
  222. }
  223. #endif
  224.  
  225. /* Callbacks */
  226. static void
  227. exposeCB(w, client_data, call_data)
  228.     Widget w;
  229.     caddr_t client_data;
  230.     GlxDrawCallbackStruct *call_data;
  231. {
  232.     view.width  = call_data->width-1;
  233.     view.height = call_data->height-1;
  234. #ifdef USE_GL
  235.     GLXwinset(XtDisplay(w), call_data->window);
  236. #else
  237.     glXMakeCurrent(XtDisplay(w), call_data->window, call_data->context);
  238. #endif
  239.     drawscene (XtDisplay(w), call_data->window, dx, dy);
  240. }
  241.  
  242. static void
  243. overlayExposeCB(w, client_data, call_data)
  244.     Widget w;
  245.     caddr_t client_data;
  246.     GlxDrawCallbackStruct *call_data;
  247. {
  248. #ifdef USE_GL
  249.     GLXwinset(XtDisplay(w), call_data->window);
  250. #else
  251.     glXMakeCurrent(XtDisplay(w), call_data->window, call_data->context);
  252. #endif
  253.     drawhouse();
  254. }
  255.  
  256. static void
  257. resizeCB(w, client_data, call_data)
  258.     Widget w;
  259.     caddr_t client_data;
  260.     GlxDrawCallbackStruct *call_data;
  261. {
  262.     view.width  = call_data->width-1;
  263.     view.height = call_data->height-1;
  264. #ifdef USE_GL
  265.     GLXwinset(XtDisplay(w), call_data->window);
  266.     viewport(0, (Screencoord) call_data->width-1,
  267.          0, (Screencoord) call_data->height-1);
  268.     drawscene (XtDisplay(w), call_data->window, dx, dy);
  269.     GLXwinset(XtDisplay(w), overlayWindow(w));
  270.     viewport(0, (Screencoord) call_data->width-1,
  271.          0, (Screencoord) call_data->height-1);
  272.     drawhouse();
  273. #else
  274.     glXMakeCurrent(XtDisplay(w), call_data->window, call_data->context);
  275.     glViewport(0, call_data->width-1, 0, call_data->height-1);
  276.     drawscene (XtDisplay(w), call_data->window, dx, dy);
  277.     glXMakeCurrent(XtDisplay(w), overlayWindow(w), overlayContext(w));
  278.     glViewport(0, call_data->width-1, 0, call_data->height-1);
  279.     drawhouse();
  280. #endif
  281. }
  282.  
  283. static void
  284. initCB(w, client_data, call_data)
  285.     Widget w;
  286.     caddr_t client_data;
  287.     GlxDrawCallbackStruct *call_data;
  288. {
  289. #ifdef USE_GL
  290.     GLXwinset(XtDisplay(w), call_data->window);
  291. #else
  292.     GLenum error;
  293.  
  294.     glXMakeCurrent(XtDisplay(w), call_data->window, call_data->context);
  295. #endif
  296.     view.width  = call_data->width-1;
  297.     view.height = call_data->height-1;
  298.     initialize_gl();
  299.     dx = call_data->width / 2;
  300.     dy = call_data->height / 2;
  301. #ifdef USE_OVERLAY
  302. #ifdef USE_GL
  303.     GLXwinset(XtDisplay(w), overlayWindow(w));
  304.     initialize_overlay(w);
  305. #else
  306.     glXMakeCurrent(XtDisplay(w), overlayWindow(w), overlayContext(w));
  307.     initialize_overlay(w);
  308.     error = glGetError();
  309.     if(error != GL_NO_ERROR)
  310.         printf("OpenGL error: %s\n",gluErrorString(error));
  311. #endif
  312. #endif
  313. }
  314.  
  315. static void
  316. inputCB(w, client_data, call_data)
  317.     Widget w;
  318.     caddr_t client_data;
  319.     GlxDrawCallbackStruct *call_data;
  320. {
  321.     char buffer[1];
  322.     KeySym keysym;
  323.     static Position oldx, oldy, newx, newy;
  324.     static Boolean buttonDown = FALSE;
  325.  
  326. #ifdef USE_GL
  327.     GLXwinset(XtDisplay(w), call_data->window);
  328. #else
  329.     GLboolean           isStereoSupported;
  330.  
  331.     glXMakeCurrent(XtDisplay(w), call_data->window, call_data->context);   
  332. #endif
  333.     switch(call_data->event->type)
  334.     {
  335.     case KeyRelease:
  336.     /* It is necessary to convert the keycode to a keysym before
  337.      * it is possible to check if it is an escape
  338.      */
  339.     if (XLookupString((XKeyEvent *)call_data->event,
  340.                       buffer,1,&keysym,NULL) == 1 &&
  341.         keysym == (KeySym)XK_Escape)
  342.         exit(0);
  343.     break;
  344.     case ButtonPress:
  345.     switch(call_data->event->xbutton.button)
  346.     {
  347.     case Button1:
  348.         buttonDown = TRUE;
  349.         oldx = newx = call_data->event->xbutton.x;
  350.         oldy = newy = call_data->event->xbutton.y;
  351.         break;
  352.       case Button2:
  353.         XtVaSetValues (w, GlxNsingleBuffer, TRUE, NULL);
  354. #ifdef USE_STEREO
  355.         stereoMode = MONO;
  356.             glDrawBuffer(GL_BACK);
  357.             glGetBooleanv(GL_STEREO, &isStereoSupported);
  358.             printf("isStereoSupported = %d\n",isStereoSupported);
  359.             drawscene (XtDisplay(w), call_data->window, dx, dy);
  360. #else
  361.         bufferMode = SINGLE;
  362.             drawscene (XtDisplay(w), call_data->window, dx, dy);
  363. #endif
  364.         break;
  365.  
  366.       case Button3:
  367.         XtVaSetValues (w, GlxNsingleBuffer, FALSE, NULL);
  368. #ifdef USE_STEREO
  369.         stereoMode = STEREO;
  370.             glGetBooleanv(GL_STEREO, &isStereoSupported);
  371.             printf("isStereoSupported = %d\n",isStereoSupported);
  372. #else
  373.         bufferMode = DOUBLE;
  374. #endif
  375.             drawscene (XtDisplay(w), call_data->window, dx, dy);
  376.         break;
  377.     }
  378.     break;
  379.     case ButtonRelease:
  380.     switch(call_data->event->xbutton.button)
  381.     {
  382.     case Button1:
  383.         buttonDown = FALSE;;
  384.         break;
  385.     }
  386.     break;
  387.     case MotionNotify:
  388.     if (buttonDown && call_data->event->xmotion.state & Button1Mask)
  389.     {
  390.         oldx = newx;
  391.         oldy = newy;
  392.         newx = call_data->event->xbutton.x;
  393.         newy = call_data->event->xbutton.y;
  394.         dx += newx-oldx;
  395.         /* GL and X have opposite y coordinates so subtract from dy */
  396.         dy -= newy-oldy;
  397.             drawscene (XtDisplay(w), call_data->window, dx, dy);
  398.     }
  399.     break;
  400.     }
  401. }
  402.  
  403. initialize_gl () {
  404. #ifdef USE_GL
  405.     long xmaxscrn, ymaxscrn;     /* maximum size of screen in x and y       */
  406.     long xscrnsize;              /* size of screen in x used to set globals */
  407.  
  408.     xscrnsize = getgdesc(GD_XPMAX);       /* get/set screen size[/aspect] */
  409.     if (xscrnsize == 1280) {
  410.          xmaxscrn = 1279;
  411.          ymaxscrn = 1023;
  412.          keepaspect(5, 4);
  413.     } else if (xscrnsize == 1024) {
  414.          xmaxscrn = 1023;
  415.          ymaxscrn = 767;
  416.          keepaspect(4, 3);
  417.     } else {
  418.         fprintf(stderr, "Something's EXTREMELY wrong:  ");
  419.         fprintf(stderr, "xscrnsize=%d\n", xscrnsize);
  420.         exit(-1) ;
  421.     }
  422.     shademodel (FLAT);
  423. #else
  424. /* Define the initial projection */
  425.     glViewport(0, 0, view.width, view.height);
  426.     glMatrixMode(GL_PROJECTION);
  427.     glLoadIdentity();
  428.     glOrtho(0, (double)view.width, 0, (double)view.height, -1.0, 1.0);
  429.     glMatrixMode(GL_MODELVIEW);
  430.     glLoadIdentity();
  431. #endif
  432. }
  433.  
  434. initialize_overlay(Widget w)
  435. {
  436.     int      stat;
  437.     Arg      args[2];
  438.     Colormap overlayColormap;
  439.     XColor   color;
  440.  
  441. #ifdef USE_GL
  442.     mapcolor (1, 255, 0, 255);
  443.     mapcolor (2, 0, 255, 255);
  444. #else
  445.     XtSetArg(args[0], GlxNoverlayColormap, &overlayColormap);
  446.     XtGetValues(w, args, 1);
  447.  
  448.     color.pixel = 1;
  449.     color.red   = 65535;
  450.     color.green = 0;
  451.     color.blue  = 65535;
  452.     stat = XAllocColor(XtDisplay(w), overlayColormap, &color);
  453.     if(!stat)
  454.         printf("Overlay XAllocColor failed\n");
  455.  
  456.     color.pixel = 2;
  457.     color.red   = 0;
  458.     color.green = 65535;
  459.     color.blue  = 65535;
  460.     stat = XAllocColor(XtDisplay(w), overlayColormap, &color);
  461.     if(!stat)
  462.         printf("Overlay XAllocColor failed\n");
  463.  
  464.     glViewport(0, 0, view.width, view.height);
  465.     glMatrixMode(GL_PROJECTION);
  466.     glLoadIdentity();
  467.     glOrtho(0, (double)view.width, 0, (double)view.height, -1.0, 1.0);
  468.     glMatrixMode(GL_MODELVIEW);
  469.     glLoadIdentity();
  470. #endif
  471. }
  472.  
  473. /*  Everytime through the loop, draw only the car, not the house.  */
  474. drawscene (display, window, x, y)
  475. Display *display;
  476. Window  window;
  477. int     x, y;
  478. {
  479. #ifdef USE_GL
  480.     color (BLACK);
  481.     clear ();
  482.     drawcar (x, y);
  483.     gflush();
  484.     if (bufferMode == DOUBLE)
  485.     swapbuffers ();
  486. #else
  487.     GLenum error;
  488.  
  489.     glClearColor(0, 0, 0, 0);
  490.     glClear(GL_COLOR_BUFFER_BIT);
  491. #ifdef USE_STEREO
  492.     if(stereoMode == STEREO)
  493.     {
  494.          int eye;
  495.  
  496.          for(eye = 0 ; eye < 1 ; eye++)
  497.          {
  498.              if(eye == 0)
  499.                  glDrawBuffer(GL_BACK_LEFT);
  500.              else
  501.                  glDrawBuffer(GL_BACK_RIGHT);
  502.              drawcar (x, y);
  503.          }
  504.      }else
  505.          drawcar (x, y);
  506. #else
  507.     drawcar (x, y);
  508. #endif
  509.     if (bufferMode == DOUBLE)
  510.         glXSwapBuffers(display, window);
  511.     error = glGetError();
  512.     if(error != GL_NO_ERROR)
  513.         printf("OpenGL error: %s\n",gluErrorString(error));
  514.  
  515. #endif
  516. }
  517.  
  518. /*  draw a car with several colors.
  519.  *  The car itself is drawn with  the front window first.  Then the front
  520.  *  window is flipped over (scaled) for the  rear  window.  The translate
  521.  *  routine moves the car to an (x,y) position.
  522.  */
  523. drawcar (x, y)
  524. int     x, y;
  525. {
  526.     float   fx, fy;
  527. #ifndef USE_GL
  528.     static  int first=1;
  529.     static GLUquadricObj *quadric;
  530. #endif
  531.  
  532.  
  533.     fx = (float) x;
  534.     fy = (float) y;
  535. #ifdef USE_GL
  536.     pushmatrix ();
  537.     translate (fx, fy, 0.0);        /*  move to mouse location  */
  538.     color (BLUE);                   /*  wheels  */
  539.     circfi (-75, -75, 20);
  540.     circfi (75, -75, 20);
  541.     color (RED);                    /*  car body  */
  542.     pmv2i (-150, -50);
  543.     pdr2i (-125, 0);
  544.     pdr2i (125, 0);
  545.     pdr2i (150, -50);
  546.     pclos ();
  547.     color (YELLOW);                 /*  front window  */
  548.     drawwindow ();
  549.     color (GREEN);                  /*  rear window  */
  550.     scale (-1.0, 1.0, 1.0);
  551.     drawwindow ();
  552.     popmatrix ();
  553. #else
  554.     if(first)
  555.     {
  556.         first = 0;
  557.         quadric = gluNewQuadric();
  558.     }
  559.     glPushMatrix();
  560.        glTranslatef (fx, fy, 0.0);
  561.        glColor3f(0.0, 0.0, 1.0);
  562.        glPushMatrix();
  563.           glTranslatef (-75.0, -75.0, 0.0);
  564.           gluDisk(quadric, 0.0, 20, 36, 1);
  565.           glTranslatef (150.0, 0.0, 0.0);
  566.           gluDisk(quadric, 0.0, 20, 36, 1);
  567.        glPopMatrix();
  568.        glColor3f(1.0, 0.0, 0.0);
  569.        glBegin(GL_QUADS);
  570.          glVertex2i(-150, -50);
  571.          glVertex2i(-125, 0);
  572.          glVertex2i(125, 0);
  573.          glVertex2i(150, -50);
  574.        glEnd();
  575.        drawwindow ();
  576.        glColor3f(1.0, 1.0, 0.0);
  577.        drawwindow ();
  578.        glColor3f(0.0, 1.0, 0.0);
  579.        glScalef(-1.0, 1.0, 1.0);
  580.        drawwindow();
  581.     glPopMatrix();
  582. #endif
  583. }
  584.  
  585. /*  draw a window for the car  */
  586. drawwindow () {
  587. #ifdef USE_GL
  588.     pmv2i (0, 0);
  589.     pdr2i (0, 50);
  590.     pdr2i (50, 50);
  591.     pdr2i (75, 0);
  592.     pclos ();
  593. #else
  594.     glBegin(GL_QUADS);
  595.       glVertex2i(0, 0);
  596.       glVertex2i(0, 50);
  597.       glVertex2i(50, 50);
  598.       glVertex2i(75, 0);
  599.     glEnd();
  600. #endif
  601. }
  602.  
  603. /*  draw a house in two colors at a fixed position, specified by the trans-
  604.  *  late routine.  The house is drawn with colors in the 4D overlay bitplanes.
  605.  */
  606. drawhouse () {
  607. #ifdef USE_GL
  608.     color (0);
  609.     clear ();
  610.     pushmatrix ();
  611.     translate (200.0, 100.0, 0.0);     /*  move house into position  */
  612.     color (1);                         /*  roof   */
  613.     pmv2i (0, 0);
  614.     pdr2i (0, 250);
  615.     pdr2i (350, 250);
  616.     pdr2i (350, 0);
  617.     pclos ();
  618.     color (2);                         /*  1st floor  */
  619.     pmv2i (175, 400);
  620.     pdr2i (0, 250);
  621.     pdr2i (350, 250);
  622.     pclos ();
  623.     popmatrix ();
  624.     gflush();
  625. #else
  626.     glClear(GL_COLOR_BUFFER_BIT);
  627.     glPushMatrix();
  628.     glTranslatef(200.0, 100.0, 0.0);
  629.     glIndexi(1);
  630.     glBegin(GL_QUADS);
  631.       glVertex2i(0, 0);
  632.       glVertex2i(0, 250);
  633.       glVertex2i(350, 250);
  634.       glVertex2i(350, 0);
  635.     glEnd();
  636.     glIndexi(2);
  637.     glBegin(GL_TRIANGLES);
  638.       glVertex2i(175, 400);
  639.       glVertex2i(0, 250);
  640.       glVertex2i(350, 250);
  641.     glEnd();
  642.     
  643.     /* ..... */
  644.     glPushMatrix();
  645. #endif
  646. }
  647.